package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.dao.BlogMapper;
import com.itheima.dao.BlogSortMapper;
import com.itheima.dao.TagMapper;
import com.itheima.pojo.Blog;
import com.itheima.pojo.BlogSort;
import com.itheima.pojo.Tag;
import com.itheima.service.BlogService;
import com.itheima.utils.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName BlogServiceImpl
 * @Description 博客表 服务实现类
 * @Author pengkaka
 * @Date 2020/8/4 11:27
 * @Version 1.0
 **/
@Service
public class BlogServiceImpl implements BlogService {


    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private BlogSortMapper blogSortMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private RedisTemplate redisTemplate;


    // 新增博客
    @Override
    public void add(Blog blog) {
        String uid = UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");
        blog.setUid(uid);
        blog.setStatus(1);
        blog.setCreateTime(new Date());
        blog.setUpdateTime(new Date());
        blog.setClickCount(0);
        blog.setCollectCount(0);
        blog.setLevel(0);
        blog.setSort(0);
        blog.setStartComment(1);
        blogMapper.insert(blog);
    }

    /**
     * 通过Uid获取博客内容
     *
     * @param uid
     * @return
     */
    @Override
    public String getBlogByUid(String uid) {
        String content = blogMapper.getBlogByUid(uid);
        return content;
    }

    /**
     * 通过uid获取博客收藏数
     *
     * @param uid
     * @return
     */
    @Override
    public Integer getBlogPraiseCountByUid(String uid) {
        Integer content = blogMapper.getBlogPraiseCountByUid(uid);
        return content;
    }

    /**
     * 通过Uid获取博客分类UID
     *
     * @param uid
     * @return
     */
    @Override
    public String getBlogSortUid(String uid) {
        String blogSortUid = blogMapper.getBlogSortUid(uid);
        return blogSortUid;
    }

    /**
     * 通过blogSortUid 获取相同的类型博客
     *
     * @param blogSortUid
     * @return
     */
    @Override
    public List<String> getBlogContentList(String blogSortUid) {
        List<String> blogContentList = blogMapper.getBlogContentList(blogSortUid);
        return blogContentList;
    }


    // 查询所有博客
    @Override
    public List<Blog> list() {
        List<Blog> blogList = blogMapper.selectAll();
        return blogList;
    }


    // 删除博客
    @Override
    public void delete(Blog blog) {
        blog.setStatus(0);
        blogMapper.updateByPrimaryKeySelective(blog);
    }

    //删除选中博客
    @Override
    public void deleteBatch(List<Blog> blogList) {
        for (Blog blog : blogList) {
            blog.setStatus(0);
            blogMapper.updateByPrimaryKeySelective(blog);
        }
    }

    //编辑博客
    @Override
    public void edit(Blog blog) {
        Integer status = blog.getStatus();
        if (status == 0) {
            throw new RuntimeException("博客已被删除,不能编辑");
        }
        blog.setUpdateTime(new Date());
        blogMapper.updateByPrimaryKeySelective(blog);

    }

    //根据uid给博客点赞
    @Override
    public void updateCollectCount(String uid) {
        blogMapper.updateCollectCountByUid(uid);
    }


    //根据标签获取相关的博客
    @Override
    public Page<Blog> getBlogContentListPage(String tagUid, Integer currentPage, Integer pageSize) {

        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("tagUid", tagUid);
        Page<Blog> blogContentList = (Page<Blog>) blogMapper.selectByExample(example);
        return blogContentList;
    }


    //根据作者搜索blog
    @Override
    public Page<Blog> searchBlogByAuthor(String author, Integer currentPage, Integer pageSize) {
        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("author", author);
        Page<Blog> blogContentList = (Page<Blog>) blogMapper.selectByExample(example);
        return blogContentList;
    }

    //根据博客分类UID获取相关的博客
    @Override
    public Page<Blog> searchBlogBySort(String blogSortUid, Integer currentPage, Integer pageSize) {
        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("blogSortUid", blogSortUid);
        Page<Blog> blogContentList = (Page<Blog>) blogMapper.selectByExample(example);
        return blogContentList;
    }

    //根据关键字查询Blog
    @Override
    public Page<Blog> sqlSearchBlog(String keyword, Integer currentPage, Integer pageSize) {
        if (currentPage == null) {
            currentPage = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.orLike("title", "%" + keyword + "%");
        criteria.orLike("content", "%" + keyword + "%");
        Page<Blog> blogContentList = (Page<Blog>) blogMapper.selectByExample(example);
        return blogContentList;
    }

    // 获取博客的归档日期
    @Override
    public Set<String> getBlogTimeSortList() {
        //从Redis中获取内容
        String monthResult = (String) redisTemplate.opsForValue().get("MONTH_SET");
        //判断redis中时候包含归档的内容
        if (StringUtils.isNotEmpty(monthResult)) {
            Set monthSet = JSON.parseObject(monthResult, Set.class);
            return monthSet;
        }

        // 第一次启动的时候归档
        Example example = new Example(Blog.class);
        example.setOrderByClause("create_time desc");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("isPublish", 1)
                .andEqualTo("status", 1);
        List<Blog> blogList = blogMapper.selectByExample(example);
        // 给博客设置标签和分类
        blogList = this.setBlog(blogList);

        // 封装相应的map和monthSet
        Map<String, List<Blog>> map = new HashMap<>();
        Set<String> monthSet = new TreeSet<>();

        blogList.forEach(blog -> {
            Date createTime = blog.getCreateTime();
            String month = new SimpleDateFormat("yyyy年MM月").format(createTime);
            monthSet.add(month);
            if (map.get(month) == null) {
                List<Blog> list = new ArrayList<>();
                list.add(blog);
                map.put(month, list);
            } else {
                List<Blog> list = map.get(month);
                list.add(blog);
                map.put(month, list);
            }
        });

        // 缓存该月份下的所有文章  key: 月份   value：月份下的所有文章
        map.forEach((key, value) -> {
            redisTemplate.opsForValue().set("BLOG_SORT_BY_MONTH:" + key, JSON.toJSONString(value));
        });

        // 将set存到redis中
        redisTemplate.opsForValue().set("MONTH_SET", JSON.toJSONString(monthSet));

        return monthSet;
    }

    // 通过月份获取文章列表
    @Override
    public List<Blog> getArticleByMonth(String monthDate) {
        if (StringUtils.isEmpty(monthDate)) {
            throw new RuntimeException("参数错误");
        }
        
        //从Redis中获取内容
        String blogResult = (String) redisTemplate.opsForValue().get("BLOG_SORT_BY_MONTH" + monthDate);

        //判断redis中时候包含该日期下的文章
        if (StringUtils.isNotEmpty(blogResult)) {
            List<Blog> blogList = JSON.parseObject(blogResult,List.class);
            return blogList;
        }


        // 第一次启动的时候归档
        Example example = new Example(Blog.class);
        example.setOrderByClause("create_time desc");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("isPublish", "1")
                .andEqualTo("status", 1);
        List<Blog> blogList = blogMapper.selectByExample(example);
        // 给博客设置标签和分类
        blogList = this.setBlog(blogList);

        // 封装相应的map和monthSet
        Map<String, List<Blog>> map = new HashMap<>();
        Set<String> monthSet = new TreeSet<>();

        blogList.forEach(blog -> {
            Date createTime = blog.getCreateTime();
            String month = new SimpleDateFormat("yyyy年MM月").format(createTime);
            monthSet.add(month);
            if (map.get(month) == null) {
                List<Blog> list = new ArrayList<>();
                list.add(blog);
                map.put(month, list);
            } else {
                List<Blog> list = map.get(month);
                list.add(blog);
                map.put(month, list);
            }
        });

        // 缓存该月份下的所有文章  key: 月份   value：月份下的所有文章
        map.forEach((key, value) -> {
            redisTemplate.opsForValue().set("BLOG_SORT_BY_MONTH:" + key, JSON.toJSONString(value));
        });

        // 将set存到redis中
        redisTemplate.opsForValue().set("MONTH_SET", JSON.toJSONString(monthSet));

        List<Blog> list = map.get(monthDate);

        return list;
    }

    // 条件+分页查询
    @Override
    public Page<Blog> findPage(Map<String, Object> searchMap) {
        Integer currentPage = (Integer) searchMap.get("currentPage");
        if (currentPage == null) {
            currentPage = 1;
        }
        Integer pageSize = (Integer) searchMap.get("pageSize");
        if (pageSize == null) {
            pageSize = 10;
        }
        PageHelper.startPage(currentPage, pageSize);
        Example example = createExample(searchMap);
        return (Page<Blog>) blogMapper.selectByExample(example);
    }

    // 根据状态获取博客数量
    @Override
    public Integer getBlogCount(int status) {
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("isPublish", 1)
                .andEqualTo("status", status);
        Integer count = blogMapper.selectCountByExample(example);

        return count;
    }

    // 获取一年内的文章贡献数
    @Override
    public Map<String, Object> getBlogContributeCount() {
        // 获取今天结束时间
        String endTime = DateUtils.getNowTime();
        // 获取365天前的日期
        Date temp = DateUtils.getDate(endTime, -365);

        String startTime = DateUtils.dateTimeToStr(temp);

        // 获取数据库相关数据:map的key是DATE,value是COUNT
        List<Map<String, Object>> blogContributeMap = blogMapper.getBlogContributeCount(startTime, endTime);
        // 获取一年的每一天的集合
        List<String> dateList = DateUtils.getDayBetweenDates(startTime, endTime);

        // 将数据重新封装
        Map<String, Object> dateMap = new HashMap<>();

        for (Map<String, Object> itemMap : blogContributeMap) {
            dateMap.put(itemMap.get("DATE").toString(), itemMap.get("COUNT"));
        }

        List<List<Object>> resultList = new ArrayList<>();
        for (String item : dateList) {
            Integer count = 0;
            if (dateMap.get(item) != null) {
                count = Integer.valueOf(dateMap.get(item).toString());
            }
            List<Object> objectList = new ArrayList<>();
            objectList.add(item);
            objectList.add(count);
            resultList.add(objectList);
        }

        Map<String, Object> resultMap = new HashMap<>();
        List<String> contributeDateList = new ArrayList<>();
        contributeDateList.add(startTime);
        contributeDateList.add(endTime);
        resultMap.put("contributeDate", contributeDateList);
        resultMap.put("blogContributeCount", resultList);

        return resultMap;
    }

    // 获取每个分类下文章数目
    @Override
    public List<Map<String, Object>> getBlogCountByBlogSort() {
        List<Map<String, Object>> blogCountByBlogSort = blogMapper.getBlogCountByBlogSort();
        // 将list封装为map
        Map<String, Integer> blogSortMap = new HashMap<>();
        for (Map<String, Object> item : blogCountByBlogSort) {
            String blogSortUid = String.valueOf(item.get("blog_sort_uid"));
            Object object = item.get("count");
            Integer count = 0;
            if (object != null) {
                count = Integer.parseInt(object.toString());
            }
            blogSortMap.put(blogSortUid, count);
        }
        // 根据blogSortUid查询blogSort,并将uid和sortName封装为map
        Set<String> blogSortUids = blogSortMap.keySet();
        Map<String, String> blogSortEntityMap = new HashMap<>();
        if (blogSortUids.size() > 0) {
            for (String blogSortUid : blogSortUids) {
                BlogSort blogSort = blogSortMapper.selectByPrimaryKey(blogSortUid);
                blogSortEntityMap.put(blogSort.getUid(), blogSort.getSortName());
            }
        }

        // 封装结果
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        for (Map.Entry<String, Integer> entry : blogSortMap.entrySet()) {
            String blogSortUid = entry.getKey();
            if (blogSortEntityMap.get(blogSortUid) != null) {
                String blogSortName = blogSortEntityMap.get(blogSortUid);
                Integer count = entry.getValue();
                Map<String, Object> itemResultMap = new HashMap<>();
                itemResultMap.put("blogSortUid", blogSortUid);
                itemResultMap.put("name", blogSortName);
                itemResultMap.put("value", count);
                resultList.add(itemResultMap);
            }
        }
        return resultList;
    }

    // 通过标签获取博客数目
    @Override
    public List<Map<String, Object>> getBlogCountByTag() {
        List<Map<String, Object>> blogCountByTag = blogMapper.getBlogCountByTag();
        // 将list封装为map
        Map<String, Integer> tagMap = new HashMap<>();
        for (Map<String, Object> item : blogCountByTag) {
            String tagUid = String.valueOf(item.get("tag_uid"));
            Object object = item.get("count");
            Integer count = 0;
            if (object != null) {
                count = Integer.parseInt(object.toString());
            }
            // 如果只有一个tagUid
            if (tagUid.length() == 32) {
                // 如果map中没有这个值
                if (tagMap.get(tagUid) == null) {
                    tagMap.put(tagUid, count);
                } else {
                    Integer tempCount = tagMap.get(tagUid) + count;
                    tagMap.put(tagUid, tempCount);
                }
            } else {
                // 长度大于32,说明含有多个tagUid
                if (StringUtils.isNotEmpty(tagUid)) {
                    String[] split = tagUid.split(",");
                    for (String str : split) {
                        if (tagMap.get(str) == null) {
                            tagMap.put(str, count);
                        } else {
                            Integer tempCount = tagMap.get(str) + count;
                            tagMap.put(str, tempCount);
                        }
                    }
                }
            }
        }

        // 根据tagUid查询Tag,并将uid和content封装为map
        Set<String> tagUids = tagMap.keySet();
        Map<String, String> tagEntityMap = new HashMap<>();
        if (tagUids.size() > 0) {
            for (String tagUid : tagUids) {
                Tag tag = tagMapper.selectByPrimaryKey(tagUid);
                tagEntityMap.put(tag.getUid(), tag.getContent());
            }
        }

        // 封装结果
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        for (Map.Entry<String, Integer> entry : tagMap.entrySet()) {
            String tagUid = entry.getKey();
            if (tagEntityMap.get(tagUid) != null) {
                String tagContent = tagEntityMap.get(tagUid);
                Integer count = entry.getValue();

                Map<String, Object> itemResultMap = new HashMap<>();
                itemResultMap.put("tagUid", tagUid);
                itemResultMap.put("name", tagContent);
                itemResultMap.put("value", count);
                resultList.add(itemResultMap);
            }
        }
        return resultList;
    }

    /**
     * 根据分类id分页查询
     *
     * @param uid
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public Page<Blog> getArticleByBlogSortUid(String uid, Integer currentPage, Integer pageSize) {
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        example.createCriteria().andEqualTo("blogSortUid", uid);
        return (Page<Blog>) blogMapper.selectByExample(example);
    }

    // 获取首页最新的博客
    @Override
    public List<Blog> getNewBlog(Integer currentPage, Integer pageSize) {
        // 从缓存中获取第一页的内容
        if (currentPage == 1L) {
            String new_blog = (String) redisTemplate.opsForValue().get("NEW_BLOG");
            if (new_blog != null) {
                List<Blog> list = JSON.parseObject(new_blog, List.class);
                return list;
            }
        }

        // 获取最新的博客存入redis
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        example.setOrderByClause("create_time desc");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("status", 1);
        criteria.andEqualTo("isPublish", "1");
        List<Blog> blogList = blogMapper.selectByExample(example);
        blogList = setBlog(blogList);

        // 将最新博客存入redis
        redisTemplate.opsForValue().set("NEW_BLOG", JSON.toJSONString(blogList));

        return blogList;
    }

    // 获取首页排行博客
    @Override
    public List<Blog> getHotBlog(Integer pageSize) {
        // 从redis获取内容,判断redis中是否有文章
        String hot_blog = (String) redisTemplate.opsForValue().get("HOT_BLOG");
        if (hot_blog != null) {
            List<Blog> list = JSON.parseObject(hot_blog, List.class);
            return list;
        }

        // 获取博客列表,并设置博客中相应内容,存入redis
        PageHelper.startPage(1, pageSize);
        Example example = new Example(Blog.class);
        // 设置根据点击数排序
        example.setOrderByClause("click_count desc");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("status", 1);
        criteria.andEqualTo("isPublish", "1");
        List<Blog> blogList = blogMapper.selectByExample(example);
        blogList = setBlog(blogList);

        // 将排行博客存入redis
        redisTemplate.opsForValue().set("HOT_BLOG", JSON.toJSONString(blogList));

        return (Page<Blog>) blogList;
    }

    // 通过推荐等级获取博客列表
    @Override
    public Page<Blog> getBlogPageByLevel(Integer level, Integer currentPage, Integer useSort) {
        // 设置推荐等级对应的pagesize
        Integer pageSize = 0;
        switch (level) {
            case 0: {
                pageSize = 15;
            }
            break;
            case 1: {
                pageSize = 5;
            }
            break;
            case 2: {
                pageSize = 2;
            }
            break;
            case 3: {
                pageSize = 3;
            }
            break;
            case 4: {
                pageSize = 5;
            }
            break;
        }
        // 获取符合条件的博客列表
        PageHelper.startPage(currentPage, pageSize);
        Example example = new Example(Blog.class);
        // 设置排序规则
        if (useSort == 0) {
            example.setOrderByClause("create_time desc");
        } else {
            example.setOrderByClause("sort desc");
        }
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("status", 1);
        criteria.andEqualTo("isPublish", "1");
        List<Blog> blogList = blogMapper.selectByExample(example);

        // 一级推荐或者二级推荐没有内容时，自动把top5填充至一级推荐和二级推荐中
        if ((level == 1 || level == 2) && blogList.size() == 0) {
            List<Blog> hotBlogList = getHotBlog(5);
            List<Blog> secondBlogList = new ArrayList<>();
            List<Blog> firstBlogList = new ArrayList<>();
            for (int a = 0; a < hotBlogList.size(); a++) {
                // 当推荐大于两个的时候
                if ((hotBlogList.size() - firstBlogList.size()) > 2) {
                    firstBlogList.add(hotBlogList.get(a));
                } else {
                    secondBlogList.add(hotBlogList.get(a));
                }
            }
            // 设置博客的分类,标签和图片内容
            firstBlogList = setBlog(firstBlogList);
            secondBlogList = setBlog(secondBlogList);

            switch (level) {
                case 1: {
                    blogList = firstBlogList;
                }
                break;
                case 2: {
                    blogList = secondBlogList;
                }
                break;
            }
            return (Page<Blog>) blogList;
        }
        blogList = setBlog(blogList);
        return (Page<Blog>) blogList;
    }

    // 按时间戳获取最新博客
    @Override
    public List<Blog> getBlogByTime(Integer currentPage, Integer pageSize) {
        List<Blog> pageList = this.getNewBlog(currentPage, pageSize);
        return pageList;
    }


    /**
     * 构建查询对象
     *
     * @param searchMap
     * @return
     */
    private Example createExample(Map<String, Object> searchMap) {
        Example example = new Example(Blog.class);
        Example.Criteria criteria = example.createCriteria();
        if (searchMap != null) {
            if (searchMap.get("keyword") != null && !"".equals(searchMap.get("keyword"))) {
                criteria.andLike("title", "%" + searchMap.get("keyword") + "%");
            }
            if (searchMap.get("tagUid") != null && !"".equals(searchMap.get("tagUid"))) {
                criteria.andEqualTo("tagUid", searchMap.get("tagUid"));
            }
            if (searchMap.get("blogSortUid") != null && !"".equals(searchMap.get("blogSortUid"))) {
                criteria.andEqualTo("blogSortUid", searchMap.get("blogSortUid"));
            }
            if (searchMap.get("isOriginal") != null && !"".equals(searchMap.get("isOriginal"))) {
                criteria.andEqualTo("isOriginal", searchMap.get("isOriginal"));
            }
            if (searchMap.get("isPublish") != null && !"".equals(searchMap.get("isPublish"))) {
                criteria.andEqualTo("isPublish", searchMap.get("isPublish"));
            }

            // 是否启动排序字段
            if (searchMap.get("useSort") == null||searchMap.get("useSort").equals(0)) {
                // 未使用，默认按时间倒序
                example.setOrderByClause("create_time DESC");
            } else {
                // 使用，默认按sort值大小倒序
                example.setOrderByClause("sort DESC");
            }
        }
        return example;
    }

    // 设置博客的分类,标签和图片内容
    private List<Blog> setBlog(List<Blog> list) {
        // 通过blog_sort_uid,tag_uid,file_uid获取相应内容
        List<Tag> tagList = new ArrayList<>();

        list.forEach(blog -> {
            // 设置BlogSort
            if (StringUtils.isNotEmpty(blog.getBlogSortUid())) {
                BlogSort blogSort = blogSortMapper.selectByPrimaryKey(blog.getBlogSortUid());
                blog.setBlogSort(blogSort);
            }
            // 设置TagList
            if (StringUtils.isNotEmpty(blog.getTagUid())) {
                String tagUids = blog.getTagUid();
                if (tagUids.length() == 32) {
                    Tag tag = tagMapper.selectByPrimaryKey(tagUids);
                    tagList.add(tag);
                    blog.setTagList(tagList);
                } else {
                    String[] split = tagUids.split(",");
                    if (split != null && split.length > 0) {
                        for (String tagUid : split) {
                            Tag tag = tagMapper.selectByPrimaryKey(tagUids);
                            tagList.add(tag);
                        }
                        blog.setTagList(tagList);
                    }
                }
            }
            // TODO 获取图片list

        });
        return list;
    }

}
